package com.wangbo.restTemplate.camvi;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.wangbo.test.util.JacksonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.*;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StopWatch;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import java.io.File;
import java.io.IOException;
import java.time.Duration;
import java.util.Arrays;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import static java.nio.charset.StandardCharsets.*;

@Slf4j
public class TestCamvi {
    public static final String IP = "192.168.88.206";
    public static final int PORT = 8080;
    public static final String USERNAME = "wangbo";
    public static final String PASSWORD = "123456";

    public static final String URL_PATTERN = "http://%s:%d/service/api/%s";
    public static final String LOGIN = "user/login";
    public static final String CHECK_QUALITY = "checkquality";
    public static final String SEARCH = "search";
    public static final String DETECT = "image/detect";
    public static final String FACE_IMAGE = "person/face-image/";
    public static final String EXTRACT_FEATURE = "extract-feature";

    public static String TOKEN = "84ewLpX3lUjrkeGJuTn7gG0hFylEG2uw";

    public static void main(String[] args) throws InterruptedException {
        RestTemplate restTemplate = new RestTemplateBuilder()
                .setConnectTimeout(Duration.ofSeconds(3L))
                .setReadTimeout(Duration.ofSeconds(3L))
                .errorHandler(new DefaultResponseErrorHandler(){
            /**
             * 设置RestTemplate自带的异常处理器不做异常处理
             **/
            @Override
            public void handleError(ClientHttpResponse response) {
            }
        }).build();

        String token = test01(restTemplate);
        TOKEN = token;

        // 检查图片质量
//        boolean pass = test02(restTemplate, TOKEN, new File("C:\\Users\\Administrator\\Pictures\\微信图片_20210822105921.jpg"));
//        System.out.printf("图片质量：%b%n", pass);


        // 批量 camvi search
//        StopWatch stopWatch = new StopWatch();
//        stopWatch.start("5张");
//        for (int i = 0; i < 1; i++) {
//            test03(restTemplate, TOKEN, new File("D:\\test"));
//        }
//        stopWatch.stop();
//        stopWatch.start("10张");
//        for (int i = 0; i < 2; i++) {
//            test03(restTemplate, TOKEN, new File("D:\\test"));
//        }
//        stopWatch.stop();
//        stopWatch.start("20张");
//        for (int i = 0; i < 4; i++) {
//            test03(restTemplate, TOKEN, new File("D:\\test"));
//        }
//        stopWatch.stop();
//        stopWatch.start("30张");
//        for (int i = 0; i < 6; i++) {
//            test03(restTemplate, TOKEN, new File("D:\\test"));
//        }
//        stopWatch.stop();
//        stopWatch.start("40张");
//        for (int i = 0; i < 8; i++) {
//            test03(restTemplate, TOKEN, new File("D:\\test"));
//        }
//        stopWatch.stop();
//        stopWatch.start("50张");
//        for (int i = 0; i < 10; i++) {
//            test03(restTemplate, TOKEN, new File("D:\\test"));
//        }
//        stopWatch.stop();
//        System.out.println(stopWatch.prettyPrint());

        // 人脸侦测
//        test04(restTemplate,TOKEN,"D:\\temp\\bg_5934.jpg");

        // 多线程  camvi search
//        StopWatch stopWatch = new StopWatch();
//        stopWatch.start("1线程100张");
//        test05(restTemplate, token, new File("D:\\test"), 20, 1);
//        stopWatch.stop();
//        stopWatch.start("5线程100张");
//        test05(restTemplate, token, new File("D:\\test"), 20, 5);
//        stopWatch.stop();
//        stopWatch.start("10线程100张");
//        test05(restTemplate, token, new File("D:\\test"), 20, 10);
//        stopWatch.stop();
//        stopWatch.start("20线程100张");
//        test05(restTemplate, token, new File("D:\\test"), 20, 20);
//        stopWatch.stop();
//        System.out.println(stopWatch.prettyPrint());

//        test07(restTemplate,TOKEN,9999L);

//        File dir = new File("E:\\未识别");
//        int okNum = 0;
//        int badNum = 0;
//        for (File file : dir.listFiles()) {
//            if (test02(restTemplate, TOKEN, file)) {
//                okNum++;
//            } else {
//                badNum++;
//            }
//        }
//        System.out.printf("符合要求：%d 张，不符合要求：%d 张%n", okNum, badNum);


        // 提取特征值
        String featureStr = test08(restTemplate, TOKEN, new File("D:\\temp\\微信图片_20220217141905.jpg"));
        System.out.println(featureStr);

        // feature 字符串识别
//        test09(restTemplate, TOKEN, featureStr);

    }

    /**
     * 登录
     **/
    private static String test01(RestTemplate restTemplate) {
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        param.add("username",USERNAME);
        param.add("password", Base64.getEncoder().encode(PASSWORD.getBytes(UTF_8)));

        String url = String.format(URL_PATTERN, IP, PORT, LOGIN);
        String result = restTemplate.postForObject(url, param, String.class);
        return result;
    }

    /**
     * 检查图片质量
     **/
    private static boolean test02(RestTemplate restTemplate, String token, File file) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", token);
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        String url = String.format(URL_PATTERN, IP, PORT, CHECK_QUALITY);
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        String str = Base64.getEncoder().encodeToString(FileUtil.readBytes(file));
        param.add("image-data", "data:image/jpeg;base64," + str);

        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(param, headers);
        String result = restTemplate.postForObject(url, httpEntity, String.class);
        Map map = JacksonUtil.toMap(result);
        boolean pass = "pass".equals(map.get("result"));
        return pass;

    }

    /**
     * 批量人脸识别
     **/
    private static void test03(RestTemplate restTemplate, String token, File dir) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", token);
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        String url = String.format(URL_PATTERN, IP, PORT, SEARCH);
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();

        for (File file : dir.listFiles()) {
            String str = Base64.getEncoder().encodeToString(FileUtil.readBytes(file));
            param.add("image-data", "data:image/jpeg;base64," + str);
            param.add("calibrated-threshold", 50);

            HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(param, headers);
            String result = restTemplate.postForObject(url, httpEntity, String.class);
//            System.out.println(result);
//            System.out.println("[]".equals(result));
        }

    }

    /**
     * 人脸检测
     **/
    private static void test04(RestTemplate restTemplate, String token, String path) {
        File file = new File(path);

        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", token);
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        String url = String.format(URL_PATTERN, IP, PORT, DETECT);
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        String str = Base64.getEncoder().encodeToString(FileUtil.readBytes(file));
        param.add("image-data", "data:image/jpeg;base64," + str);
        param.add("tag", "waves");
        param.add("detect-liveness", false);

        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(param, headers);
        String result = restTemplate.postForObject(url, httpEntity, String.class);
        System.out.println(result);
    }

    /**
     * 多线程 camvi search
     **/
    public static void test05(RestTemplate restTemplate, String token, File dir, int time, int threadNum) throws InterruptedException {
        File[] files = dir.listFiles();
        assert files != null;
        CountDownLatch countDownLatch = new CountDownLatch(files.length * time);

        ConcurrentLinkedQueue<File> taskQueue = new ConcurrentLinkedQueue<>();
        for (int i = 0; i < time; i++) {
            taskQueue.addAll(Arrays.asList(files));
        }

        for (int i = 0; i < threadNum; i++) {
            Thread thread = new Thread(() -> {
                while (!taskQueue.isEmpty()) {
                    File file = taskQueue.poll();

                    HttpHeaders headers = new HttpHeaders();
                    headers.set("Authorization", token);
                    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
                    String url = String.format(URL_PATTERN, IP, PORT, SEARCH);
                    MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();

                    String str = Base64.getEncoder().encodeToString(FileUtil.readBytes(file));
                    param.add("image-data", "data:image/jpeg;base64," + str);
                    param.add("calibrated-threshold", 50);

                    HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(param, headers);
                    String result = restTemplate.postForObject(url, httpEntity, String.class);
                    countDownLatch.countDown();
                }
            }, String.format("thread_%d", i));
            thread.start();
        }
        countDownLatch.await();
    }

    /**
     * 抓拍
     * 结果：只有正在camvi上进行视频流解析的摄像头能够抓拍
     **/
    private static void test06(RestTemplate restTemplate, String token) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", token);
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        String url = String.format("http://%s:%s/service/api/%s", "58.221.101.74", "8090", "camera/snapshot");
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        param.add("url", "rtsp://admin:szlx12345@192.168.87.201/Streaming/Channels/101");

        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(param, headers);
        String result = restTemplate.postForObject(url, httpEntity, String.class);

        Map map = JacksonUtil.toMap(result);
        String imgStr = (String) map.get("snapshot");
        byte[] bytes = Base64.getDecoder().decode(imgStr);
        FileUtil.writeBytes(bytes, "/home/wangbo/test.jpg");
        System.out.println(result);
    }

    /**
     * 人脸图片
     */
    public static void test07(RestTemplate restTemplate, String token, long faceId) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", token);
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        String url = "http://139.196.32.4:8080/service/api/person/face-image/" + faceId;
        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(headers);
        ResponseEntity<byte[]> response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, byte[].class);
        System.out.println(new String(response.getBody()));

        String str = Base64.getEncoder().encodeToString(response.getBody());
        System.out.println(str);
    }

    /**
     * 提取特征值
     */
    public static String test08(RestTemplate restTemplate, String token, File file) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", token);
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        String url = String.format(URL_PATTERN, IP, PORT, EXTRACT_FEATURE);
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        String str = Base64.getEncoder().encodeToString(FileUtil.readBytes(file));
        param.add("image-data", "data:image/jpeg;base64," + str);

        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(param, headers);
        String result = restTemplate.postForObject(url, httpEntity, String.class);
        Map map = JacksonUtil.toMap(result);
        return (String) (map.get("feature"));
    }

    /**
     * 人脸识别（FeatureStr 实现）
     */
    public static void test09(RestTemplate restTemplate, String token, String featureStr) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", token);
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        String url = String.format(URL_PATTERN, IP, PORT, SEARCH);
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        param.add("feature-data", featureStr);

        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(param, headers);
        String result = restTemplate.postForObject(url, httpEntity, String.class);
        System.out.println(result);
    }


}
